package captor.windowsystem.formcomponent.aop.abstractpointcutpanel;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;

import org.w3c.dom.DOMException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import captor.modelsystem.Model;
import captor.modelsystem.Project;
import captor.projectsystem.xmlgen.CCBuffer;
import captor.windowsystem.formcomponent.FormComponent;
import captor.windowsystem.formcomponent.Parameter;

/**
 * 
 * Abstract Pointcut form component.
 * 
 * <p>
 * Abstract pointcut concretization for crosscutting domains.
 * </p>
 * 
 * @author Carlos Alberto
 * 
 */
public class AbstractPointcutList extends FormComponent implements KeyListener {

	public static final long serialVersionUID = 115;
	public static final Dimension TABLE_SIZE = new Dimension(432, 140);

	KeyListenTable concreteValueList;
	DefaultTableModel  tableModel;
	JLabel refNameLabel;
	JLabel descriptionLabel;

	private String id;
	private String refName;
	private String description;

	public AbstractPointcutList(Model model, DefaultMutableTreeNode node) {
		super(model, node);
		id = "";
		refName = "";
		create();
	}

	// -------------------------------------------------------------------------

	public void create() {
		this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));

		Dimension labelDimension = new Dimension(100, 20);

		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));

		JPanel abstractPointcutPanel = new JPanel();
		abstractPointcutPanel.setLayout(new BoxLayout(abstractPointcutPanel,
				BoxLayout.LINE_AXIS));
		JLabel abstractPointcutLabel = new JLabel("Abstract Pointcut: ");
		abstractPointcutLabel.setHorizontalAlignment(SwingConstants.LEFT);
		abstractPointcutLabel.setMinimumSize(labelDimension);
		abstractPointcutLabel.setMaximumSize(labelDimension);
		abstractPointcutLabel.setPreferredSize(labelDimension);

		refNameLabel = new JLabel("refName");
		refNameLabel.setHorizontalAlignment(SwingConstants.LEFT);
		refNameLabel.setMinimumSize(new Dimension(405, 18));
		refNameLabel.setMaximumSize(new Dimension(405, 18));
		refNameLabel.setPreferredSize(new Dimension(405, 18));
		abstractPointcutPanel.add(abstractPointcutLabel);
		abstractPointcutPanel.add(refNameLabel);

		JPanel descriptionPanel = new JPanel();
		descriptionPanel.setLayout(new BoxLayout(descriptionPanel,
				BoxLayout.LINE_AXIS));
		JLabel descriptionTextLabel = new JLabel("Description: ");
		descriptionTextLabel.setHorizontalAlignment(SwingConstants.LEFT);
		descriptionTextLabel.setMinimumSize(labelDimension);
		descriptionTextLabel.setMaximumSize(labelDimension);
		descriptionTextLabel.setPreferredSize(labelDimension);
		descriptionLabel = new JLabel("description");
		descriptionLabel.setHorizontalAlignment(SwingConstants.LEFT);
		descriptionLabel.setMinimumSize(new Dimension(405, 18));
		descriptionLabel.setMaximumSize(new Dimension(405, 18));
		descriptionLabel.setPreferredSize(new Dimension(405, 18));
		descriptionPanel.add(descriptionTextLabel);
		descriptionPanel.add(descriptionLabel);

		JPanel concreteValuePanel = new JPanel();
		concreteValuePanel.setLayout(new BoxLayout(concreteValuePanel, BoxLayout.LINE_AXIS));		
		tableModel = new DefaultTableModel(new String[][]{}, new String[]{"Concrete Value List"});		
		concreteValueList = new KeyListenTable(tableModel, this.model);	
		JScrollPane scrollPane = new JScrollPane (concreteValueList);
		concreteValueList.setSize(TABLE_SIZE);
		concreteValueList.setPreferredSize(TABLE_SIZE);
		concreteValueList.setMaximumSize(TABLE_SIZE); 
        scrollPane.setSize(TABLE_SIZE);
        scrollPane.setPreferredSize(TABLE_SIZE);
        scrollPane.setMaximumSize(TABLE_SIZE);
        //button panel
        JButton plus = new JButton("Add");
        plus.addActionListener(new java.awt.event.ActionListener() {
          public void actionPerformed(java.awt.event.ActionEvent e) {
        	  addRowActionPerformed(e);
          }});
        JButton minus = new JButton("Remove");
        minus.addActionListener(new java.awt.event.ActionListener() {
        	public void actionPerformed(java.awt.event.ActionEvent e) {
        		deleteRowActionPerformed(e);
        	}});
        Dimension d = new Dimension(75,25);
        minus.setPreferredSize(d);
        minus.setMinimumSize(d);
        minus.setMaximumSize(d);
        plus.setPreferredSize(d);
        plus.setMinimumSize(d);
        plus.setMaximumSize(d);
        JPanel bPanel = new JPanel();
        bPanel.setLayout(new BoxLayout(bPanel, BoxLayout.Y_AXIS));
        bPanel.add(Box.createRigidArea(new Dimension(5,5)));
        bPanel.add(plus);        
        bPanel.add(Box.createRigidArea(new Dimension(5,5)));
        bPanel.add(minus);
        bPanel.add(Box.createRigidArea(new Dimension(5,60)));
        
        concreteValuePanel.add(scrollPane);
        concreteValuePanel.add(new JLabel(" "));
        concreteValuePanel.add(bPanel);
        concreteValuePanel.add(Box.createHorizontalGlue());

		panel.add(abstractPointcutPanel);
		panel.add(descriptionPanel);
		panel.add(concreteValuePanel);

		this.add(panel);
		this.add(Box.createRigidArea(new Dimension(10, 0)));
	}

	// -------------------------------------------------------------------------

	public void parseParameters() {
		String id2 = (String) parameter.get("ID");
		if (id2 != null) {
			id = id2;
		}

		String refNameValue = (String) parameter.get("REFNAME");
		if (refNameValue != null) {
			refNameLabel.setText(refNameValue);
			refName = refNameValue;
		}

		String descriptionValue = (String) parameter.get("DESCRIPTION");
		if (descriptionValue != null) {
			descriptionLabel.setText(descriptionValue);
			description = descriptionValue;
		}

	}

	// -------------------------------------------------------------------------

	public void toXML(CCBuffer out) {
		out.newLine();
		out.ident();

		String id = (String) parameter.get("ID");
		out.appendln("<pointcutlist name=\"" + id + "\" refname=\"" + refName
				+ "\">");
		out.ident();
		for (int i = 0; i < concreteValueList.getRowCount(); i++) {
			String concreteValue = (String) concreteValueList.getValueAt(i, 0);
			if ((concreteValue != null) && (concreteValue.length() > 0)
					&& (!concreteValue.equals(""))) {
				out.appendln("<concretevalue>"
						+ concreteValueList.getValueAt(i, 0)
						+ "</concretevalue>");
			}
		}
		out.dident();
		out.appendln("</pointcutlist>");
		out.dident();
	}

	// -------------------------------------------------------------------------

	public boolean validateFields() {

		String id = (String) parameter.get("ID");
		if (id == null) {
			cleanErrorLine();
			addErrorLine("There is an error in the meta-model.\nThe formElement PointcutList doesn't have a ID parameter.");
			return false;
		}

		String refName = (String) parameter.get("REFNAME");
		if (refName == null) {
			cleanErrorLine();
			addErrorLine("There is an error in the meta-model.\nThe formElement PointcutList doesn't have a REFNAME parameter.");
			return false;
		}

		return true;
	}

	// -------------------------------------------------------------------------

	public void load(Node data) {
		String id = (String) parameter.get("ID");
		if (id == null)
			return;

		NodeList nodeList = data.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node = nodeList.item(i);
			if (node.getNodeName().toUpperCase().equals("POINTCUTLIST")) {
				NamedNodeMap nnm = node.getAttributes();
				Node nameAtt = nnm.getNamedItem("name");
				refName = nnm.getNamedItem("refname").getNodeValue();
				refNameLabel.setText(refName);
				if (nameAtt.getNodeValue().toUpperCase().equals(
						id.toUpperCase())) {					
					fillMainValues(node);
				}
			}
		}
	}

	// -------------------------------------------------------------------------

	public String getId() {
		return id;
	}

	// -------------------------------------------------------------------------

	public boolean validateParameters() {

		if ((model.getProject().getNewProjectDomain() == null)
				|| (!model.getProject().getNewProjectDomain()
						.isCrosscuttingDomain())) {
			errorMsg = "This element can be used only on crosscutting domains projects.\n";
			return false;
		}

		String id = (String) parameter.get("ID");
		if (id == null) {
			errorMsg = "This element requires the 'id' parameter.\n";
			return false;
		}

		String refName = (String) parameter.get("REFNAME");
		if ((refName == null) || (refName.equals(""))) {
			errorMsg = "This element requires the 'refname' parameter.\n";
			return false;
		}

		return true;
	}

	// -------------------------------------------------------------------------

	public Vector getRequiredParameters() {
		Vector v = new Vector();

		v.add(new Parameter("id", "string", "", "1", "Unique identifier", "",
				true));
		v.add(new Parameter("refname", "string", "", "refName",
				"Abstract pointcut identifier name", "", true));
		v.add(new Parameter("description", "string", "", "description",
				"Pointcut description", "", false));

		return v;
	}

	// -------------------------------------------------------------------------

	public void updateValues() {
	}

	// -------------------------------------------------------------------------

	public String getValues() {
		return "";
	}

	// -------------------------------------------------------------------------
	// -------------------------------------------------------------------------
	// -------------------------------------------------------------------------
	// The methods below are specific for this component
	// -------------------------------------------------------------------------
	// -------------------------------------------------------------------------

	public void keyTyped(KeyEvent e) {
	}

	public void keyPressed(KeyEvent e) {
	}

	public void keyReleased(KeyEvent e) {
		model.getProject().setStatus(Project.UNSAVED);
	}

	// -------------------------------------------------------------------------

	private void fillMainValues(Node node) {

		NodeList nodeList = node.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node node2 = nodeList.item(i);
			if (node2.getNodeName().toUpperCase().equals("CONCRETEVALUE")) {
				try {
					tableModel.addRow(new String[]{node2.getFirstChild().getNodeValue()});
				} catch (DOMException e) {
					return;
				} catch (Exception e) {
					return;
				}
			}
		}
	}
	
	private void addRowActionPerformed(ActionEvent e){
		tableModel.addRow(new String[]{""});
	}
	private void deleteRowActionPerformed(ActionEvent e){
		if ( tableModel.getRowCount() > 0 && concreteValueList.getSelectedRow() >= 0 )  {
	        tableModel.removeRow(concreteValueList.getSelectedRow());
			model.getProject().setStatus(Project.UNSAVED);
	    }
	}
}
